/** 
* @Title: ThreadScopeShareData.java 
* @Package com.lh.threadtest.t5 
* @Description: TODO
* @author Liu 
* @date 2018年1月16日 下午4:38:55 
* @version V1.0 
*/
package com.lh.threadtest.t6;

import java.util.Random;

/***
 * 
* @ClassName: ThreadLocalTest 
* @Description: ThreadLocal类及应用技巧
* 
* ThreadLocal的作用类似于Map，只不过它的作用更加强大，使用起来更加简单
* 
* 总结：
* 	一个ThreadLocal代表一个变量，故其中只能放一个数据，若有两个变量都要实现线程内共享，则要定义两个
* ThreadLocal对象；如果有100个共享变量呢？那就先定义一对象来封装这100个变量，然后在ThreadLocal中
* 存储这一个对象。
* 
* 将ThreadLocal与类的单例结合起来，使得线程共享数据功能对外隐藏起来，外部不用关心内部实现的细节，也更加简洁，而且这样设计更加优雅。
* 
* @author Liu
* @date 2018年1月16日 下午5:56:31 
*
 */
public class ThreadLocalTest3 {
	private static ThreadLocal<Integer> x = new ThreadLocal<>();
	
	public static void main(String[] args) {
		for(int i = 0; i < 2; i++){
			new Thread(new Runnable() {
				
				public void run() {
					Integer data = new Random().nextInt();
					System.out.println(Thread.currentThread().getName()
							+ " has put data:" + data
							);
					x.set(data);
					
					MyThreadData myThreadData = MyThreadData.getThreadInstance();
					myThreadData.setName("name" + data);
					myThreadData.setAge(data);
					
					new A().get();
					new B().get();
					new C().get();
				}
			}).start();
		}
	}

	static class A {
		 void get(){
			Integer data = x.get();
			MyThreadData myThreadScopeData = MyThreadData.getThreadInstance();
			System.out.println("A from " + Thread.currentThread().getName()
					+ " get data:" + data + " data2: " +myThreadScopeData
					);
		}
	}

	static class B {
		 void get(){
			Integer data = x.get();
			MyThreadData myThreadScopeData = MyThreadData.getThreadInstance();
			System.out.println("B from " + Thread.currentThread().getName()
					+ " get data:" + data + " data2: " +myThreadScopeData
					);
		}
	}

	static class C {
		 void get(){
			Integer data = x.get();
			MyThreadData myThreadScopeData = MyThreadData.getThreadInstance();
			System.out.println("C from " + Thread.currentThread().getName()
					+ " get data:" + data + " data2: " +myThreadScopeData
					);
		}
	}

}

//ThreadLocal结合类的单例使用，使得共享数据变得更加优雅
class MyThreadData{
	private MyThreadData(){}
	
//	private static MyThreadData instance = null;
	
	private static ThreadLocal<MyThreadData> map = new ThreadLocal<>();
	
	public /*synchronized*/ static MyThreadData getThreadInstance(){
		MyThreadData instance = map.get();
		
		if(instance == null){
			instance = new MyThreadData();
			map.set(instance);
		}
		return instance;
	}
	
	private String name;
	private int age;
	
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	public int getAge() {
		return age;
	}
	public void setAge(int age) {
		this.age = age;
	}
	@Override
	public String toString() {
		return "MyThreadScopeData [name=" + name + ", age=" + age + "]";
	}
	
}
